package com.zeyi.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zeyi.blog.dao.UserDao;
import com.zeyi.blog.entity.User;
import com.zeyi.blog.exception.TokenExpiredException;
import com.zeyi.blog.service.MenuService;
import com.zeyi.blog.service.RoleService;
import com.zeyi.blog.service.UserService;
import com.zeyi.blog.social.ThirdUser;
import com.zeyi.blog.util.JwtTokenUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;

/**
 * 用户表(User)表服务实现类
 *
 * @author 黎先森
 * @since 2020-07-19 18:19:00
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Resource
    RoleService roleService;

    @Resource
    MenuService menuService;

    @Resource
    BCryptPasswordEncoder passwordEncoder;

    @Resource
    JwtTokenUtil jwtTokenUtil;

    @Override
    @Transactional
    public User thirdLogin(ThirdUser thirdUser) {
        User user = this.baseMapper.getByThirdAuth(thirdUser);
        if (user == null) {
            user = new User();
            user.setUsername(thirdUser.getUsername());
            user.setAvatar(thirdUser.getAvatar());
            this.baseMapper.insert(user);
            this.baseMapper.insertThirdUser(user.getId(), thirdUser.getProviderId(), thirdUser.getId());
            roleService.grantRole(user.getId(), Collections.singletonList("6e2464dfacfc7bd9d0d15b397eb7e001"));
        } else {
            if (!user.getAvatar().equals(thirdUser.getAvatar())) {
                user.setAvatar(thirdUser.getAvatar());
                this.baseMapper.updateById(user);
            }
        }
        return user;
    }

    @PostAuthorize("(returnObject != null && returnObject.username == authentication.name) || hasAnyAuthority('SUPER_ADMIN')")
    @Override
    public User getById(Serializable id) {
        return super.getById(id);
    }

    @Override
    public User findById(String id) {
        return super.getById(id);
    }

    @PreAuthorize("(#entity != null && #entity.username == authentication.name) || hasAnyAuthority('SUPER_ADMIN')")
    @Override
    public boolean updateById(User entity) {
        return super.updateById(entity);
    }

    @Override
    public Page<User> queryPage(Integer currentPage, Integer size, Map<String, Object> map) {
        Page<User> page = PageHelper.startPage(currentPage, size);
        this.baseMapper.queryPage(map);
        return page;
    }

    @Override
    public boolean saveUser(User user) {
        if (user.getPassword() != null && !user.getPassword().equals("")) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        }
        return this.save(user);
    }

    @Override
    public User getByMobile(String mobile) {
        return this.baseMapper.getByMobile(mobile);
    }

    @Override
    public String refreshToken(String token) {
        return jwtTokenUtil.refreshToken(token);
    }

    @Override
    public User getUserInfo(String token) throws TokenExpiredException {
        String userId = jwtTokenUtil.getUserIdFromToken(token);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("username", "avatar").eq("id", userId);
        User user = this.baseMapper.selectOne(wrapper);
        user.setMenus(menuService.getMenusByUserId(userId));
        user.setRoles(roleService.getRoleCodeByUserId(userId));
        return user;
    }
}